package com.bitmain.mmst.miner.monitor;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import com.bitmain.mmst.domain.AbstractMinerJob;
import com.bitmain.mmst.domain.MinerDetectBatch;
import com.bitmain.mmst.domain.MinerSetupJob;
import com.bitmain.mmst.domain.MinerUpdateJob;
import com.bitmain.mmst.feature.cache.GlobalDataBuffer;
import com.bitmain.mmst.miner.AbstractScheduledTask;
import com.bitmain.mmst.miner.TaskExecuteEvent;
import com.bitmain.mmst.miner.TaskExecuteListener;
import com.bitmain.mmst.miner.statistic.MinerStatistician;

public class MinerMonitor extends AbstractScheduledTask{
	
	private static final AtomicInteger NUM = new AtomicInteger(0);
	
	public void initialize(){
		initJobExecutor();
		initNetworkDetector();
	}
	
	/**
	 * 矿机运行时状态检测器
	 */
	public void executeRuntimeDetector(){
		MinerRuntimeDetector detector = new MinerRuntimeDetector();
		detector.addExecuteListener(new TaskExecuteListener(){
			@Override
			public void executeDone(TaskExecuteEvent event) {
				OverviewHashrate((MinerDetectBatch) event.data);
			}
		});
		detector.execute();
	}

	private void OverviewHashrate(MinerDetectBatch batch) {
		ExecutorService service = Executors.newSingleThreadExecutor();
		service.execute(new Runnable(){
			@Override
			public void run() {
				MinerStatistician.executeHashrateOverview(batch);
			}
		});
		service.shutdown();
	}

	/**
	 * 每个任务执行间隔时间
	 */
	private static long JOB_INTERVAL = 1_000;
	private boolean jobRunning = false;
	/**
	 * 初始化矿机维护任务执行器
	 */
	private void initJobExecutor() {
		if(jobRunning)
			return;
		System.out.println("【初始化】矿机维护任务执行器");
		ExecutorService service = Executors.newSingleThreadExecutor();
		service.execute(new Runnable(){
			@Override
			public void run() {
				while(true){
					try {
						if(GlobalDataBuffer.getRunningJob() == null){
							AbstractMinerJob job = GlobalDataBuffer.takeJob();
							switch(job.getJobType()){
							case UPDATE:
								MinerUpdateJob updateJob = (MinerUpdateJob) job;
								new MinerFirmwareUpdater(updateJob).execute();
								break;
							case SETUP:
								MinerSetupJob setupJob = (MinerSetupJob) job;
								new MinerConfigurationSetter(setupJob).execute();
								break;
							}
						}
					} catch (Exception e) {
						//System.out.println(e);
						//System.out.println("【异常】矿机维护任务异常");
					}
					//System.out.println("");
					try {
						Thread.sleep(JOB_INTERVAL);
					} catch (InterruptedException e) {
					}
				}
			}
		});
		service.shutdown();
		System.out.println("【完成】矿机维护任务");
		jobRunning = true;
	}

	private static long NETWORK_INTERVAL = 1_000;
	private boolean networkRunning = false;
	
	private void initNetworkDetector(){
		networkRunning = false;
		if(networkRunning){
			return;
		}
		System.out.println("【初始化】网络状态检测器");
		ExecutorService service = Executors.newSingleThreadExecutor();
		service.execute(new Runnable(){
			@Override
			public void run() {
				while(NUM.get()<100){
				try {
					if(numNetworkDetector()==0){
						System.out.println("【网络状态检测器】"+NUM);
						new MinerNetworkDetector().execute();
						NUM.getAndIncrement();
					}
					Thread.sleep(NETWORK_INTERVAL);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		});
		service.shutdown();
		System.out.println("【完成】网络状态检测器");
		networkRunning = true;
	}
	
	/**
	 * 记录正在执行中的运行时状态检测器
	 */
	private static final AtomicInteger NUM_RUNTIME_DETECTOR = new AtomicInteger(0);
	/**
	 * 记录正在执行中的网络状态检测器
	 */
	private static final AtomicInteger NUM_NETWORK_DETECTOR = new AtomicInteger(0);
	
	static int numRuntimeDetector(){
		return NUM_RUNTIME_DETECTOR.get();
	}
	static int incrementRuntimeDetector(){
		return NUM_RUNTIME_DETECTOR.getAndIncrement();
	}
	static int decrementRuntimeDetector(){
		return NUM_RUNTIME_DETECTOR.decrementAndGet();
	}
	public static int numNetworkDetector(){
		return NUM_NETWORK_DETECTOR.get();
	}
	public static int incrementNetworkDetector(){
		return NUM_NETWORK_DETECTOR.getAndIncrement();
	}
	public static int decrementNetworkDetector(){
		return NUM_NETWORK_DETECTOR.decrementAndGet();
	}
}